#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
#include <cstring>
#include <string>
using namespace std;

#define NUM 5

class ThreadData
{
public:
    ThreadData(int num)
    {
        _threadname = "thread_" + to_string(num);
    }

    string get_name()
    {
        return _threadname;
    }

private:
    string _threadname;
};

//int g_val = 0;   //全局变量是所有线程共享的
//__thread int g_val = 0;  // __thread 修饰的全局变量 每个线程都有一份
void* ThreadRoutine(void* argc)
{
    ThreadData* td = static_cast<ThreadData*>(argc);
    //for(int i = 1; i <= 5; i++)
    for(int i = 1; i > 0; i++)
    {
        //线程的临时变量独立
        //printf("threadname: %s , tid: %p, i: %d, &i: %p\n", td->get_name().c_str(), pthread_self(), i, &i);
        
        //全局变量是共享的
        //g_val++;
        //printf("threadname: %s , tid: %p, g_val: %d, &g_val: %p\n", td->get_name().c_str(), pthread_self(), g_val, &g_val);
        printf("threadname: %s , tid: %p, \n", td->get_name().c_str(), pthread_self());
        sleep(1);
    }
}

int main()
{
    vector<pthread_t> tids;
    vector<ThreadData*> tds;
    for(int i = 1; i <= NUM; i++)
    {
        ThreadData* td = new ThreadData(i);
        tds.push_back(td);
        pthread_t tid;
        pthread_create(&tid, nullptr, ThreadRoutine, (void*)td);
        printf("create a thread : %s, tid : %p\n", td->get_name().c_str(), tid);
        tids.push_back(tid);
    }

    // 线程分离
    for(auto tid : tids)
    {
        pthread_detach(tid); // 表示这个线程不需要等待
    }

    for(auto tid : tids)
    {
        int n = pthread_join(tid, nullptr);
        printf("n = %d, who = 0x%x, why: %s\n", n, tid, strerror(n));
    }

    for(auto td : tds)
    {
        delete td;
    }

    cout << "主线程结束啦" << endl; 
    return 0;
}

// 线程的参数和返回值也可以传对象
// class Request
// {
// public:
//     Request(int start, int end)
//         : _start(start)
//         , _end(end)
//         {}

//     int Add()
//     {
//         int sum = 0;
//         for(int i = _start; i <= _end; i++)
//         {
//             sum += i;
//         }

//         return sum;
//     }

// private:
//     int _start;
//     int _end;
// };

// class Response
// {
// public:
//     Response(int ret, int exitcode)
//         : _ret(ret)
//         , _exitcode(exitcode)
//     {}

//     int GetRet()
//     {
//         return _ret;
//     }

//     int GetExitCode()
//     {
//         return _exitcode;
//     }
// private:
//     int _ret = 0;
//     int _exitcode = 0;
// };

// void* sumCount(void* arg)
// {
//     Request* rt = static_cast<Request*>(arg);
//     int ret = rt->Add();
//     Response* rps = new Response(ret, 0);
    
//     delete rt;

//     return (void*)rps;
// }

// int main()
// {
//     pthread_t tid;
//     Request* rt = new Request(1, 100); 

//     pthread_create(&tid, nullptr, sumCount, (void*)rt);
//     void* retval;
//     pthread_join(tid, &retval);

//     Response* rps = static_cast<Response*>(retval);

//     cout << "result : " << rps->GetRet() << " exitcode : " << rps->GetExitCode() << endl;
// }


// void* threadRoutine(void* arg)
// {
//     int cnt = 100;
//     while(cnt--)
//     {
//         cout << "i am a thread, my pid is " << getpid() << endl;
//         sleep(1);

//         if(cnt == 90)
//         {
//             pthread_exit((void*)11);
//         } 
//     }

//     return (void*)(((long long)arg) * 10);
// }

// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, threadRoutine, (void*)10);
//
//     int cnt = 10;
//     while(cnt--)
//     {
//         cout << "i am main processs, my pid is " << getpid() << endl;
//         sleep(1); 
//         if(cnt == 7)
//         {
//             pthread_cancel(tid);
//         }
//     }

//     void* retval;
//     pthread_join(tid, &retval);
//     cout << "thread return : " << (long long)retval << endl;

//     return 0;
// }
